package org.appenders.log4j2.elasticsearch;

/*-
 * #%L
 * log4j2-elasticsearch
 * %%
 * Copyright (C) 2019 Rafal Foltynski
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;

public class JacksonHandlerInstantiator extends HandlerInstantiator {

    private final VirtualProperty[] virtualProperties;
    private final ValueResolver valueResolver;
    private final VirtualPropertyFilter[] virtualPropertyFilters;

    private VirtualPropertiesWriter instance;

    /**
     * @param virtualProperties properties to be appended
     * @param valueResolver used to resolve properties if {@link VirtualProperty#isDynamic()} is true
     */
    public JacksonHandlerInstantiator(VirtualProperty[] virtualProperties, ValueResolver valueResolver) {
        this(virtualProperties, valueResolver, new VirtualPropertyFilter[0]);
    }

    public JacksonHandlerInstantiator(
            VirtualProperty[] virtualProperties,
            ValueResolver valueResolver,
            VirtualPropertyFilter[] virtualPropertyFilters
    ) {
        this.virtualProperties = virtualProperties;
        this.valueResolver = valueResolver;
        this.virtualPropertyFilters = virtualPropertyFilters;
    }

    @Override
    public JsonDeserializer<?> deserializerInstance(DeserializationConfig config, Annotated annotated, Class<?> deserClass) {
        return null;
    }

    @Override
    public KeyDeserializer keyDeserializerInstance(DeserializationConfig config, Annotated annotated, Class<?> keyDeserClass) {
        return null;
    }

    @Override
    public JsonSerializer<?> serializerInstance(SerializationConfig config, Annotated annotated, Class<?> serClass) {
        return null;
    }

    @Override
    public TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> config, Annotated annotated, Class<?> builderClass) {
        return null;
    }

    @Override
    public TypeIdResolver typeIdResolverInstance(MapperConfig<?> config, Annotated annotated, Class<?> resolverClass) {
        return null;
    }

    /**
     * Allows to inject {@link VirtualPropertiesWriter} in order to resolve and write {@link VirtualProperty}-ies
     *
     * @return Shared {@link VirtualPropertiesWriter}
     */
    @Override
    public VirtualPropertiesWriter virtualPropertyWriterInstance(MapperConfig<?> config, Class<?> implClass) {
        if (implClass != VirtualPropertiesWriter.class) {
            // Jackson will instantiate the class if null is returned
            return null;
        }
        if (instance == null) {
            instance = new VirtualPropertiesWriter(
                    virtualProperties,
                    valueResolver,
                    virtualPropertyFilters);
        }
        return instance;
    }

}
